package com.zhentao.datacontrol.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhentao.datacontrol.domain.dto.DataControlRuleDTO;
import com.zhentao.datacontrol.domain.entity.DataControlRule;
import com.zhentao.datacontrol.mapper.DataControlRuleMapper;
import com.zhentao.datacontrol.service.DataControlRuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DataControlRuleServiceImpl extends ServiceImpl<DataControlRuleMapper, DataControlRule> implements DataControlRuleService {

    private static final Logger log = LoggerFactory.getLogger(DataControlRuleServiceImpl.class);

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private DataControlRuleMapper dataControlRuleMapper;

    @Override
    public IPage<DataControlRuleDTO> getRulePage(int pageNo, int pageSize, Long groupId,
                                               String ruleName, String status, String publishStatus) {
        Page<DataControlRule> page = new Page<>(pageNo, pageSize);
        IPage<DataControlRule> rulePage = dataControlRuleMapper.selectPageWithGroup(page, groupId, ruleName, status, publishStatus);

        // 转换为DTO
        IPage<DataControlRuleDTO> dtoPage = new Page<>(pageNo, pageSize, rulePage.getTotal());
        List<DataControlRuleDTO> dtoList = rulePage.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        dtoPage.setRecords(dtoList);

        return dtoPage;
    }

    @Override
    public DataControlRuleDTO getRuleDetail(Long id) {
        DataControlRule rule = dataControlRuleMapper.selectById(id);
        if (rule == null) {
            return null;
        }
        return convertToDTO(rule);
    }

    @Override
    @Transactional
    public Long createRule(DataControlRuleDTO ruleDTO) {
        // 检查规则编码是否重复
        if (ruleDTO.getRuleCode() != null && checkRuleCodeExists(ruleDTO.getRuleCode(), null)) {
            throw new RuntimeException("规则编码已存在");
        }

        DataControlRule rule = new DataControlRule();
        BeanUtils.copyProperties(ruleDTO, rule);

        // 生成规则编码
        if (rule.getRuleCode() == null || rule.getRuleCode().isEmpty()) {
            rule.setRuleCode(generateNextRuleCode());
        }

        // 设置默认状态
        if (rule.getStatus() == null) {
            rule.setStatus("DRAFT");
        }
        if (rule.getPublishStatus() == null) {
            rule.setPublishStatus("UNPUBLISHED");
        }

        // 设置默认优先级
        if (rule.getRulePriority() == null) {
            rule.setRulePriority(1);
        }

        // 转换JSON字段
        convertDTOToEntity(ruleDTO, rule);

        rule.setCreatedTime(LocalDateTime.now());
        rule.setUpdatedTime(LocalDateTime.now());

        dataControlRuleMapper.insert(rule);
        return rule.getId();
    }

    @Override
    @Transactional
    public boolean updateRule(DataControlRuleDTO ruleDTO) {
        // 检查规则编码是否重复
        if (checkRuleCodeExists(ruleDTO.getRuleCode(), ruleDTO.getId())) {
            throw new RuntimeException("规则编码已存在");
        }

        DataControlRule rule = dataControlRuleMapper.selectById(ruleDTO.getId());
        if (rule == null) {
            throw new RuntimeException("规则不存在");
        }

        BeanUtils.copyProperties(ruleDTO, rule);
        convertDTOToEntity(ruleDTO, rule);
        rule.setUpdatedTime(LocalDateTime.now());

        return dataControlRuleMapper.updateById(rule) > 0;
    }

    @Override
    @Transactional
    public boolean deleteRule(Long id) {
        DataControlRule rule = new DataControlRule();
        rule.setId(id);
        rule.setIsDelete(1);
        rule.setUpdatedTime(LocalDateTime.now());

        return dataControlRuleMapper.updateById(rule) > 0;
    }

    @Override
    @Transactional
    public boolean publishRule(Long id) {
        return dataControlRuleMapper.updatePublishStatus(id, "PUBLISHED") > 0 &&
               dataControlRuleMapper.updateStatus(id, "ENABLED") > 0;
    }

    @Override
    @Transactional
    public boolean unpublishRule(Long id) {
        return dataControlRuleMapper.updatePublishStatus(id, "UNPUBLISHED") > 0;
    }

    @Override
    @Transactional
    public boolean enableRule(Long id) {
        return dataControlRuleMapper.updateStatus(id, "ENABLED") > 0;
    }

    @Override
    @Transactional
    public boolean disableRule(Long id) {
        return dataControlRuleMapper.updateStatus(id, "DISABLED") > 0;
    }

    @Override
    @Transactional
    public boolean moveRuleToGroup(Long ruleId, Long groupId) {
        return dataControlRuleMapper.moveToGroup(ruleId, groupId) > 0;
    }

    @Override
    public List<DataControlRuleDTO> getRulesByGroup(Long groupId) {
        List<DataControlRule> rules = dataControlRuleMapper.selectByGroupId(groupId);
        return rules.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public List<DataControlRuleDTO> getRuleTree() {
        List<DataControlRule> rules = dataControlRuleMapper.selectRuleTree();
        return rules.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public boolean checkRuleCodeExists(String ruleCode, Long excludeId) {
        return dataControlRuleMapper.checkRuleCodeExists(ruleCode, excludeId) > 0;
    }

    @Override
    public String generateNextRuleCode() {
        return dataControlRuleMapper.getNextRuleCode();
    }

    @Override
    @Transactional
    public boolean updateSortOrders(List<Long> ids, List<Integer> sortOrders) {
        if (ids.size() != sortOrders.size()) {
            throw new RuntimeException("参数长度不匹配");
        }

        for (int i = 0; i < ids.size(); i++) {
            dataControlRuleMapper.updateSortOrder(ids.get(i), sortOrders.get(i));
        }

        return true;
    }

    @Override
    public List<DataControlRuleDTO> getPublishedRules() {
        List<DataControlRule> rules = dataControlRuleMapper.selectPublishedRules();
        return rules.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Long copyRule(Long sourceId, String newRuleName) {
        DataControlRule sourceRule = dataControlRuleMapper.selectById(sourceId);
        if (sourceRule == null) {
            throw new RuntimeException("源规则不存在");
        }

        DataControlRule newRule = new DataControlRule();
        BeanUtils.copyProperties(sourceRule, newRule);

        newRule.setId(null);
        newRule.setRuleCode(generateNextRuleCode());
        newRule.setRuleName(newRuleName);
        newRule.setStatus("DRAFT");
        newRule.setPublishStatus("UNPUBLISHED");
        newRule.setCreatedTime(LocalDateTime.now());
        newRule.setUpdatedTime(LocalDateTime.now());

        dataControlRuleMapper.insert(newRule);
        return newRule.getId();
    }

    /**
     * 实体转DTO
     */
    private DataControlRuleDTO convertToDTO(DataControlRule rule) {
        DataControlRuleDTO dto = new DataControlRuleDTO();
        BeanUtils.copyProperties(rule, dto);

        // 转换JSON字段
        try {
            if (rule.getRuleConfig() != null) {
                @SuppressWarnings("unchecked")
                Map<String, Object> ruleConfig = objectMapper.readValue(rule.getRuleConfig(), Map.class);
                dto.setRuleConfig(ruleConfig);
            }
            if (rule.getBusinessFields() != null) {
                List<DataControlRuleDTO.BusinessFieldConfig> businessFields = objectMapper.readValue(rule.getBusinessFields(),
                    objectMapper.getTypeFactory().constructCollectionType(List.class, DataControlRuleDTO.BusinessFieldConfig.class));
                dto.setBusinessFields(businessFields);
            }
            if (rule.getParameterTables() != null) {
                List<DataControlRuleDTO.ParameterTableConfig> parameterTables = objectMapper.readValue(rule.getParameterTables(),
                    objectMapper.getTypeFactory().constructCollectionType(List.class, DataControlRuleDTO.ParameterTableConfig.class));
                dto.setParameterTables(parameterTables);
            }
            if (rule.getFilterConditions() != null) {
                @SuppressWarnings("unchecked")
                Map<String, Object> filterConditions = objectMapper.readValue(rule.getFilterConditions(), Map.class);
                dto.setFilterConditions(filterConditions);
            }
        } catch (JsonProcessingException e) {
            // 处理JSON解析异常
            log.error("JSON解析失败", e);
        }

        // 设置状态文本
        dto.setStatusText(getStatusText(rule.getStatus()));
        dto.setPublishStatusText(getPublishStatusText(rule.getPublishStatus()));

        return dto;
    }

    /**
     * DTO转实体
     */
    private void convertDTOToEntity(DataControlRuleDTO dto, DataControlRule rule) {
        try {
            if (dto.getRuleConfig() != null) {
                rule.setRuleConfig(objectMapper.writeValueAsString(dto.getRuleConfig()));
            }
            if (dto.getBusinessFields() != null) {
                rule.setBusinessFields(objectMapper.writeValueAsString(dto.getBusinessFields()));
            }
            if (dto.getParameterTables() != null) {
                rule.setParameterTables(objectMapper.writeValueAsString(dto.getParameterTables()));
            }
            if (dto.getFilterConditions() != null) {
                rule.setFilterConditions(objectMapper.writeValueAsString(dto.getFilterConditions()));
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON序列化失败", e);
        }
    }

    private String getStatusText(String status) {
        switch (status) {
            case "DRAFT": return "草稿";
            case "PUBLISHED": return "已发布";
            case "DISABLED": return "已禁用";
            default: return status;
        }
    }

    private String getPublishStatusText(String publishStatus) {
        switch (publishStatus) {
            case "UNPUBLISHED": return "未发布";
            case "PUBLISHED": return "已发布";
            default: return publishStatus;
        }
    }
}
